﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using GameEngine;
using ComputerEngine;
using Microsoft.Win32;
using GameEngine.PDNParser;
using System.Windows;
using System.Windows.Threading;
using System.IO;
using Daphne.Forms;
using Tomers.WPF.Localization;
using System.Globalization;

namespace Daphne
{
    public enum eBoardType { e2D, e3D };

    public partial class MainWindow
    {
        private eBoardType _eBoardType;


        protected void SetGameManager(GameManager mng)
        {
            _mng = mng;
            _presenter.GameManager = _mng;
            uxFigureCountCtrl.GameManager = _mng;
            uxOnMove.SetData(_sAppPath, _mng);
            uxBoard3D.SetGameManager(_mng);
            uxGameList.GameManager = mng;
            //uxMasterTab.SetGameManager(_mng);
        }

        protected void ShowGameResult(enumGameResult gameResult)
        {
            uxGameStatus.UpdateGameResult(gameResult);

            Daphne.Forms.GameResult frm = new Forms.GameResult();
            frm.SetGameResult(gameResult);
            frm.Owner = this;
            frm.ShowDialog();          
        }

        protected void SwitchGameType(eGameType gameType)
        {
            _GameType = gameType;
            uxGameStatus.UpdateGameType(gameType);
        }

        protected void GameUpdate()
        {
            uxFigureCountCtrl.Update();
            uxOnMove.Update();
            //uxMasterTab.Update();
            uxGameList.Update();            
            uxBoard2D.InvalidateVisual();
            uxBoard3D.Redraw();
            uxGameStatus.UpdateComputerLevel(_iEngineLevel);
            uxGameStatus.UpdateGameType(_GameType);
            uxGameStatus.UpdateGameResult(_mng.EvaluateGameResult());
        }

        protected void SwitchBoard(eBoardType boardType)
        {
            _eBoardType = boardType;
            if (_eBoardType == eBoardType.e2D)
            {
                uxBoard2D.Visibility = System.Windows.Visibility.Visible;
                uxBoard3D.Visibility = System.Windows.Visibility.Hidden;
                uxBoard2DRow.Height = new GridLength(1, GridUnitType.Star);
                uxBoard3DRow.Height = new GridLength(0, GridUnitType.Pixel);
                uxBoardTypeButton.IsOn = false;
            }
            else
            {
                uxBoard2D.Visibility = System.Windows.Visibility.Hidden;
                uxBoard3D.Visibility = System.Windows.Visibility.Visible;
                uxBoard2DRow.Height = new GridLength(0, GridUnitType.Pixel);
                uxBoard3DRow.Height = new GridLength(1, GridUnitType.Star);
                uxBoardTypeButton.IsOn = true;
            }

            _daphneConfig.BoardType = boardType;
        }

        protected void LoadPDNFile(string sFile)
        {
            FileStream fileStream = new FileStream(sFile, FileMode.Open);
            // read the file
            PDNRawGameList gameList;
            PDNReader reader = new PDNReader();
            if (reader.ParseFile(fileStream, out gameList) == false)
            {
                MessageBox.Show(reader.ErrorMessage, GetTextValue("APP_Error"), MessageBoxButton.OK, MessageBoxImage.Error);
                _recentFileList.RemoveFile(sFile);
                return;
            }
            fileStream.Close();

            _recentFileList.InsertFile(sFile);

            int gameIndex = 0;
            // if there are more games in the file
            if (gameList.Games.Count > 1)
            {
                Daphne.Forms.GameSelectForm form = new Daphne.Forms.GameSelectForm();
                form.Owner = this;
                form.LoadGames(gameList);
                if (form.ShowDialog() == false)
                    return;

                gameIndex = form.SelectedGameIndex;
            }

            reader.InterpretGame(gameList.Games[gameIndex], _mng);
            GameUpdate();
        }


        protected void LoadGame()
        {
            // show open file dialog
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = ".pdn";
            dlg.Filter = GetTextValue("APP_PDNFilter");
            dlg.CheckFileExists = true;
            dlg.CheckPathExists = true;
            if (dlg.ShowDialog() == true)
            {
                LoadPDNFile(dlg.FileName);
            }
        }

        protected void SaveGame()
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".pdn";
            dlg.Filter = GetTextValue("APP_PDNFilter"); 
            dlg.CheckPathExists = true;
            dlg.OverwritePrompt = true;
            if (dlg.ShowDialog() == true)
            {
                using (FileStream fileStream = new FileStream(dlg.FileName, FileMode.OpenOrCreate))
                {
                    PDNWriter writer = new PDNWriter();
                    if (writer.WriteGame(fileStream, _mng) == false)
                    {
                        MessageBox.Show(writer.Error, GetTextValue("APP_Error"), MessageBoxButton.OK, MessageBoxImage.Error);
                        return;
                    }

                    fileStream.Flush();
                    fileStream.Close();
                }

                _recentFileList.InsertFile(dlg.FileName);
            }
        }

        protected void InitStatusBar()
        {
            ClearProgressBar();
        }

        protected void ClearProgressBar()
        {
            uxProgressName.Content = GetTextValue("APP_NoProcess");
            uxProgressBar.Minimum = 0;
            uxProgressBar.Maximum = 100;
            uxProgressBar.Value = 0;
        }

        private void BackgroundProcessInit(eBackgroundProcess processType)
        {
            uxProgressBar.Value = 0;
            switch (processType)
            {
                case eBackgroundProcess.PreloadingDatabase:
                    uxProgressName.Content = GetTextValue("APP_LoadingEGTB");
                    break;
                case eBackgroundProcess.Thinking:
                    uxProgressName.Content = GetTextValue("APP_Thinking");
                    break;
            }

            uxProgressName.InvalidateVisual();
        }

        private void BackgroudProgressReport(int percent)
        {
            uxProgressBar.Value = percent;
            uxProgressBar.InvalidateVisual();
        }

        private void _engine_BackgroundProcessInit(object sender, BackgroundProcessEventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => 
                  
                    BackgroundProcessInit(e.BackgroundProcessType)
                ));
        }

        private void _engine_ProgressReport(object sender, ProgressReportEventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>

                    BackgroudProgressReport(e.ProgressPercent)
                ));
        }

        private void _engine_BackgroundProcessFinished(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>

                    ClearProgressBar()
                ));
        }

        private void _engine_MoveComputed(object sender, MoveComputedEventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>

                    ComputerMoveDone(e.OutputBitBoard)
                ));

        }

        private void uxMasterTab_MoveSetEvent(object sender, Controls.MoveSetEventArgs e)
        {
            _mng.MoveHistory.MoveToIndex(e.MoveIndex);
            GameUpdate();
            uxBoard2D.InvalidateVisual();
        }

        void uxGameList_MoveSetEvent(object sender, Controls.MoveSetEventArgs e)
        {
            _mng.MoveHistory.MoveToIndex(e.MoveIndex);
            GameUpdate();
            uxBoard2D.InvalidateVisual();
        }

        private void Set3DView(Board3D.eBoardView boardView)
        {
            _currentView = boardView;
            uxBoard3D.SetupBoardView(_currentView);
            if(boardView == Board3D.eBoardView.FromTop)
                _daphneConfig.Board3DView = eBoard3DView.TopView;
        }

        private void Set3DView(eBoard3DView view)
        {
            if (view == eBoard3DView.PersonView)
                SetPersonView();
            else
                Set3DView(Board3D.eBoardView.FromTop);
        }

        private void SetPersonView()
        {
            _daphneConfig.Board3DView = eBoard3DView.PersonView;

            if (_currentView == Board3D.eBoardView.FromTop)
            {
                _currentView = _mng.GameBoard.OnMove == enumFigureColor.White ? Board3D.eBoardView.WhiteView
                    : Board3D.eBoardView.BlackView;
            }
            else
            {
                _currentView = _currentView == Board3D.eBoardView.WhiteView ? Board3D.eBoardView.BlackView
                    : Board3D.eBoardView.WhiteView;
            }

            Set3DView(_currentView);
        }

        private void SetTheme(enumTheme theme)
        {
            uxThemeClassic.IsCheckable = true;
            uxThemeBlackWhite.IsCheckable = true;
            uxThemeMarble.IsCheckable = true;
            uxThemeClassic.IsChecked = false;
            uxThemeBlackWhite.IsChecked = false;
            uxThemeMarble.IsChecked = false;

            switch (theme)
            {
                case enumTheme.Classic:
                    uxBoard3D.SetBoardStyle(Board3D.Models.enumBoardStyle.Classic);
                    uxBoard2D.SetTheme(Board2D.eBoard2DTheme.Classic);
                    uxThemeClassic.IsChecked = true;
                    break;
                case enumTheme.BlackAndWhite:
                    uxBoard3D.SetBoardStyle(Board3D.Models.enumBoardStyle.BlackAndWhite);
                    uxBoard2D.SetTheme(Board2D.eBoard2DTheme.BlackAndWhite);
                    uxThemeBlackWhite.IsChecked = true;
                    break;
                case enumTheme.Marble:
                    uxBoard3D.SetBoardStyle(Board3D.Models.enumBoardStyle.Marble);
                    uxBoard2D.SetTheme(Board2D.eBoard2DTheme.Marble);
                    uxThemeMarble.IsChecked = true;
                    break;
            }

            _daphneConfig.Theme = theme;

            uxBoard3D.Redraw();
            uxBoard2D.Refresh();
        }

        private void AskForLanguage(bool allowCancel)
        {
            // run the form
            SelectLanguageForm frm = new SelectLanguageForm();
            if (_daphneConfig != null && string.IsNullOrWhiteSpace(_daphneConfig.LangCode) == false)
            {
                frm.LangCode = _daphneConfig.LangCode;
            }
            frm.AllowCancel = allowCancel;
            frm.ShowDialog();

            // check result
            if (frm.Result)
            {
                // language set - set the locale
                LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo(frm.LangCode);

                // set the configuration
                _daphneConfig.LangCode = frm.LangCode;
                Config.Set<DaphneConfig>(_sDaphneConfigKey, _daphneConfig);

                ClearProgressBar();
                GameUpdate();
                UpdateWindowTitle();
            }
        }

        /// <summary>
        /// Sets the graphics level
        /// </summary>
        private void SetGraphicsLevel(int level)
        {
            //if (uxBoard3D.SetGraphicsLevel(level) == false)
            //{
            //    MessageBox.Show(GetTextValue("APP_ErrorGraphicsLevel"));
            //}

            //_daphneConfig.GraphicsLevel = uxBoard3D.GetGraphicsLevel();
            //Config.Set<DaphneConfig>(_sDaphneConfigKey, _daphneConfig);
        }
    }
}
